home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
docs
/
corsoguide
/
doslibrary-4.txt
< prev
next >
Wrap
Text File
|
1996-02-22
|
9KB
|
195 lines
La dos.library
Programmando in C la dos.library costituisce l'unica eccezione a quanto
detto prima sulle librerie; infatti non vi è bisogno di aprirla perché
l'apertura e la chiusura vengono automaticamente effettuati dal
compilatore; questo per mantenere la compabilità con lo standard ANSI C
(e quindi garantire la portabilità dei programmi); infatti lo standard
prevede di gestire files senza bisogno di aprire e chiudere alcunché;
apertura e chiusura che devono quindi essere realizzate in maniera
trasparente al programmatore. Come avrete capito la dos.library mette a
disposizione le funzioni per gestire il DOS (Disk Operating System =
Sistema Operativo del Disco), cioè gestione dei files, directory, drive
et similia. Iniziamo subito con la gestione dei files, ed in particolare
con la funzione che permette di aprirne uno:
file = Open(nomefile,modalità);
dove nomefile è il puntatore alla stringa contenente il nome del file o
del dispositivo (tipo CON: o RAW:) completo di path; modalità indica la
modalità appunto con cui aprire il file e può valere MODE_OLDFILE, per
aprire un file già esistente per la lettura e scrittura (se il file non
esiste verrà segnalato un errore), MODE_NEWFILE che crea un nuovo file
per lettura e scrittura (se il file esiste già verra inizializzato
comunque); ed infine MODE_READWRITE che apre un file, sempre per operazioni
sia di lettura che di scrittura in modalità spartita (ciò significa che lo
stesso file potrà essere aperto anche da altri processi, mentre per le
precedenti modalità il file veniva bloccato, cioè altri processi non
possono accedervi fino a quando non viene chiuso dal programma che lo usa
attualmente); file è il puntatore ad una struttura FileHandle che contiene
tutte le informazioni relative al file aperto; informazioni che
necessitano a tutte le altre funzioni che operano sui file, per cui
tale puntatore dovrà essere passato a tutte le funzioni che verranno
chiamate successivamente; se il valore ritornato da Open è nullo, allora il
file non è stato aperto per qualche motivo, per cui si è verificato un
errore; vediamo un esempio:
struct FileHandle *Fh;
.
.
if ((Fh = Open("ram:pippo",MODE_OLDFILE)) == NULL)
{
printf("Non posso aprire il file pippo.\n");
exit(1);
}
Dopo aver finito di utilizzare il file, occorre chiuderlo con la seguente
funzione:
Close(file);
dove file è il puntatore a FileHandle ritornato dalla rispettiva funzione
Open. La volta scorsa abbiamo parlato delle funzioni della dos.library per
aprire e chiudere un file, le prossime istruzioni da esaminare riguardano
la gestione di quest'ultimo; i files nell'AmigaDOS vengono gestiti sia ad
accesso sequenziale che casuale (random); ciò significa che all'apertura
del file, il cursore che segna la lettura è posizionato all'inizio di
quest'ultimo e, man mano che si effettuano operazioni di lettura o di
scrittura, quest'ultimo si posiziona alla fine della lunghezza dell'ultima
operazione realizzata; in questa maniera si sfrutta un accesso sequenziale
al file, esiste tuttavia un metodo per posizionarsi in un qualsiasi punto
del file e utilizzare così un accesso casuale. La prima funzione da
analizzare è Read che, come si può intuire dal nome, realizza l'operazione
di lettura:
LungAttuale = Read(file,buffer,lunghezza);
dove file è il puntatore alla struttura FileHandle ritornata dalla funzione
Open, buffer è un puntatore ad un buffer in memoria che conterrà i dati da
leggere, e lunghezza il numero di bytes da leggere dal file; il parametro
ritornato LungAttuale indica il numero di bytes effettivamente letti
dall'operazione di Read; normalmente tale valore è positivo e serve a
verificare che il numero di bytes letti equivale effettivamente a quello
richiesto (in caso contrario si sarà raggiunto l'end-of-file); se tale
numero vale zero significa che ci si trova già sull'end-of-file e quindi
non è possibile leggere alcun byte; se tale valore risulta infine -1
significa che si è verificato un errore; osserviamo immediatamente un
esempio:
struct FileHandle *file;
LONG len;
UBYTE buffer[1000];
.
.
len = Read(file,buffer,1000);
if (len < 0) printf("Errore\n");
else if (len < 1000) printf("Letti meno bytes, raggiunto EOF");
questo esempio tenta di leggere 1000 bytes dal file identificato dalla
struttura FileHandle denominato 'file' e di inserirlo nel buffer denominato
'buffer' (che nella fattispecie è creato come vettore); se il valore
ritornato len è negativo viene stampato su video un errore, se è inferiore
a 1000 viene avvisato l'utente sempre con un messaggio.
La seconda istruzione da esaminare è Write che serve per la scrittura in un
file; la sintassi è:
LungRitorno = Write(file,buffer,lunghezza);
dove 'file' ricopre il solito significato, 'buffer' è il puntatore al buffer
contenente i dati da scrivere e 'lunghezza' indica il numero di byte da
scrivere; 'LungRitorno' indica il numero di bytes realmente scritti sul
file; anche in questo caso in presenza di errore il valore ritornato è -1;
l'esempio viene riportato qui di seguito:
struct FileHandle *file;
LONG len;
UBYTE buffer[1000];
.
.
len = Write(file,buffer,1000);
if (len < 0) printf("Errore\n");
Le istruzioni Read e Write sono non bufferizzate, ciò significa che se
leggo un solo byte alla volta il dos accederà ogni volta al file impiegando
così molto tempo; una vecchia soluzione per risolvere questo problema era
leggere un blocco di bytes riponendolo in un buffer e da lì prelevare i
singoli caratteri; dalla versione 2.0 del sistema operativo (V36) sono
previste però due funzioni che permettono di leggere e scrivere un byte
alla volta con bufferizzazione implementata dal DOS: FGetC e FPutC. La
prima preleva un carattere dalla poszione corrente del file e il secondo
inserisce un carattere nella posizione corrente del file; la sintassi di
queste è:
carattere = FGetC(file);
dove 'carattere' è il byte letto dal file puntato da 'file'.
carattere1 = FPutC(file,carattere2);
dove 'carattere2' è il byte da scrivere nel file puntato da 'file'; il
valore ritornato 'carattere1', o è identico a carattere2 o corrisponde a
EOF se si è verificato errore.
Dato che con queste operazioni viene effettuata una bufferizzazione, se dopo
la chiamata di una di queste si ha intenzione di utilizzare un Read o un
Write (che non sono bufferizzate), occorre effettuare un operazione di
scarico del buffer: Flush;
successo = Flush(file);
dove il valore ritornato indica il successo dell'operazione.
Un'altra operazione importante legata a quelle bufferizzate è UnGetC che
permette da inserire nel buffer un qualsiasi byte e che quindi verrà
acquisito nella prossima operazione di lettura (se questa è bufferizzata);
valore = UnGetC(file,carattere);
'carattere' è il byte che viene inserito nel buffer di I/O; se questi
vale -1 allora verrà reinserito nel buffer l'ultimo byte letto (sempre da
operazione bufferizzata e vale a dire FGetC); il parametro ritornato
'valore', indica il carattere inserito nel buffer o FALSE se tale carattere
non può essere inserito nel buffer.
Come abbiamo accennato, vi è la possibilità di accedere casualmente al file
mediante un istruzione che ci permette di spostarci in un punto qualsiasi di
quest'ultimo: Seek la cui sintassi è:
vecchiapos = Seek(file,posizione,modalità);
Il valore 'vecchiapos' ritornato indica la posizione assoluta (rispetto
all'inizio del file) attuale, prima che l'operazione di spostamento abbia
luogo; se il valore ritornato risulta -1, lo spostamento non è stato
effettuato per qualche motivo (indice uscito fuori dai limiti del file);
'modalità' indica il tipo di riferimento da adottare per lo spostamento,
che può valere OFFSET_BEGINNING (inizio del file), OFFSET_CURRENT
(corrente posizione del file) o OFFSET_END (fine del file); 'posizione'
è il valore che indica la nuova posizione da assumere rispetto al
riferimento indicato da 'modalità' e può essere sia negativo che positivo,
vediamo qualche esempio:
struct FileHandle *file;
LONG vecpos,pos;
.
.
vecpos = Seek(file,0,OFFSET_BEGINNING);
/* Posizionati all'inizio del file */
.
vecpos = Seek(file,0,OFFSET_END);
/* Posizionati alla fine del file */
.
vecpos = Seek(file,1,OFFSET_CURRENT);
/* Posizionati di un byte avanti alla posizione corrente */
.
vecpos = Seek(file,-1,OFFSET_END);
/* Posizionati un byte prima della fine del file */
Fino ad adesso è stato sempre indicato come dopo ogni operazione DOS, sia
possibile rilevare se quest'ultima è incorsa in un errore o meno, ma come
fare per capire qual è l'errore che è stato causato? La funzione DOS che si
occupa di identificare l'errore è IoErr:
(vp1)errore = IoErr();
(vp5)Dove errore è il codice dell'errore verificatosi; attenzione però se
l'operazione ha avuto successo e quindi non si è verificato alcun errore,
nulla si sà sul valore ritornato.
Ci sono molte altre funzioni della dos.library alcuni delle quali
importanti, che corrispondono a nuove caratteristiche del 2.0 (assegnamenti
multipli ecc.), ma quelle esaminate sono quelle che utilizzerete più spesso.